Skip to content

feat(playwright): expose default Context/Launch options on settings#5861

Merged
thomhurst merged 1 commit into
mainfrom
feat/playwright-default-options
May 8, 2026
Merged

feat(playwright): expose default Context/Launch options on settings#5861
thomhurst merged 1 commit into
mainfrom
feat/playwright-default-options

Conversation

@thomhurst
Copy link
Copy Markdown
Owner

Summary

  • Replace granular DefaultHeadless / DefaultIgnoreHttpsErrors on TUnitPlaywrightSettings with full options objects: DefaultBrowserNewContextOptions and DefaultBrowserTypeLaunchOptions.
  • One extension point now covers every Playwright option without adding a new property each time.
  • When a defaults object is set, it fully replaces the hardcoded base defaults (Locale = "en-US", ColorScheme = Light); when null, base defaults still apply.

Breaking changes

Test plan

  • Public API snapshots regenerated and accepted across net472 / net8.0 / net9.0 / net10.0.
  • CI green.

Replaces the granular DefaultHeadless/DefaultIgnoreHttpsErrors props
on TUnitPlaywrightSettings with full options objects:
DefaultBrowserNewContextOptions and DefaultBrowserTypeLaunchOptions.
A single extension point now covers every Playwright option without
adding a new property each time. When set, the option object fully
replaces the hardcoded base defaults (Locale=en-US, ColorScheme=Light).

BREAKING: removes DefaultHeadless and DefaultIgnoreHttpsErrors.
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Good direction overall — full options objects scale far better than adding a property per Playwright flag. The API snapshot updates are clean and consistent across all targets. A few concerns worth addressing:


1. All-or-nothing replacement is a usability regression

The problem: Users who only want to set IgnoreHTTPSErrors = true must now reconstruct the entire BrowserNewContextOptions, including remembering to re-apply Locale = "en-US" and ColorScheme = Light themselves. If they forget, the locale/color-scheme defaults silently vanish.

The old API (DefaultIgnoreHttpsErrors = true) was more ergonomic for single-option overrides. The new one is more powerful but less safe.

Better approach — a configurer callback:

// In TUnitPlaywrightSettings:
public Action<BrowserNewContextOptions>? ConfigureContextOptions { get; set; }

// Applied at use site:
protected virtual BrowserNewContextOptions GetContextOptions()
{
    var opts = new BrowserNewContextOptions { Locale = "en-US", ColorScheme = ColorScheme.Light };
    TUnitPlaywrightSettings.Default.ConfigureContextOptions?.Invoke(opts);
    return opts;
}

This preserves the hardcoded sensible defaults and lets users layer on top without having to know what the base defaults are. The same pattern applies to ConfigureLaunchOptions. It also eliminates the null vs "user explicitly wants empty options" ambiguity.


2. Shared mutable state risk

TUnitPlaywrightSettings.Default.DefaultBrowserTypeLaunchOptions returns the same object instance to every caller. A subclass or test that mutates it (e.g. options.Headless = true after retrieving it) would affect all concurrent or subsequent tests.

In BrowserTest.cs:

public BrowserTest() : this(TUnitPlaywrightSettings.Default.DefaultBrowserTypeLaunchOptions ?? new BrowserTypeLaunchOptions())

The reference is passed directly into the base constructor. If Playwright or user code later mutates that object, you have a shared-state bug.

Fix: Clone on read, not on write. Either clone the options object at the call site (Playwright's options classes are not ICloneable, so a copy constructor or shallow-clone helper is needed), or use the callback pattern from point 1 (which constructs a fresh object each time).


3. Duplicated fallback defaults between ContextFixture and ContextTest

Both ContextFixture.GetContextOptions() and ContextTest.ContextOptions() have identical fallback logic:

new BrowserNewContextOptions { Locale = "en-US", ColorScheme = ColorScheme.Light }

This duplication pre-existed but is now load-bearing: if someone adds another default in one place and forgets the other, behavior diverges silently. A shared static BrowserNewContextOptions CreateDefaultContextOptions() helper would make this a single source of truth.


4. Redundant nullable initializers (minor)

public BrowserTypeLaunchOptions? DefaultBrowserTypeLaunchOptions { get; set; } = null;
public BrowserNewContextOptions? DefaultBrowserNewContextOptions { get; set; } = null;

= null is the default for nullable reference types and can be removed.


Summary: The concept is right and worth shipping over the granular-property approach. The main ask before merging is either (a) adopt the callback pattern to avoid the silent-defaults-loss problem, or (b) at minimum document clearly in the XML docs that setting these replaces all defaults, so users know to re-specify Locale/ColorScheme themselves. The shared-mutable-state issue is a correctness concern worth addressing alongside.

@codacy-production
Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity

Metric Results
Complexity 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@thomhurst thomhurst enabled auto-merge (squash) May 8, 2026 23:31
@thomhurst thomhurst merged commit 0009c88 into main May 8, 2026
14 checks passed
@thomhurst thomhurst deleted the feat/playwright-default-options branch May 8, 2026 23:44
This was referenced May 9, 2026
github-actions Bot pushed a commit to IntelliTect/CodingGuidelines that referenced this pull request May 11, 2026
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.43.11 to
1.44.0.

<details>
<summary>Release notes</summary>

_Sourced from [TUnit.Core's
releases](https://github.com/thomhurst/TUnit/releases)._

## 1.44.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.44.0 -->

## What's Changed
### Other Changes
* Generated mocks live in the same namespace as the mocked type by
@​thomhurst in thomhurst/TUnit#5870
* Show multi-step test spans in class timeline, align report ordering
with execution, and correlate linked OTel activities by @​Copilot in
thomhurst/TUnit#5847
* fix: don't leak RUC onto Should-style comparer overloads (#​5857) by
@​thomhurst in thomhurst/TUnit#5873
* Fix culture-dependent timestamp in HTML test report (#​5868) by
@​thomhurst in thomhurst/TUnit#5872
* fix(mocks-http): auto-prepend `/` to partial endpoint paths (#​5838)
by @​thomhurst in thomhurst/TUnit#5874
* Replace Report.ExpandClassTimeline with [ClassTimeline] attribute by
@​thomhurst in thomhurst/TUnit#5875
* feat(assertions): make ShouldAssertion<T> implement IAssertion
(#​5824) by @​thomhurst in thomhurst/TUnit#5876
* feat(mocks): support non-span ref struct out/ref params by @​thomhurst
in thomhurst/TUnit#5878
* fix(core): fill optional params when invoking MethodDataSource via
reflection by @​thomhurst in
thomhurst/TUnit#5880
* Mocks: structural fix for Mock<T> / mocked-member name collisions by
@​thomhurst in thomhurst/TUnit#5881
* chore(mocks): promote TUnit.Mocks packages to stable by @​thomhurst in
thomhurst/TUnit#5877
### Dependencies
* chore(deps): update tunit to 1.43.41 by @​thomhurst in
thomhurst/TUnit#5863
* chore(deps): update dependency tunit.assertions.fsharp to 1.43.41 by
@​thomhurst in thomhurst/TUnit#5865
* chore(deps): bump @​babel/plugin-transform-modules-systemjs from
7.28.5 to 7.29.4 in /docs by @​dependabot[bot] in
thomhurst/TUnit#5867
* chore(deps): bump fast-uri from 3.1.0 to 3.1.2 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5862


**Full Changelog**:
thomhurst/TUnit@v1.43.41...v1.44.0

## 1.43.41

<!-- Release notes generated using configuration in .github/release.yml
at v1.43.41 -->

## What's Changed
### Other Changes
* feat(playwright): expose default Context/Launch options on settings by
@​thomhurst in thomhurst/TUnit#5861
* fix(hooks): resolve TestDiscovery hook context type by attribute kind,
not method name by @​thomhurst in
thomhurst/TUnit#5860
### Dependencies
* chore(deps): update tunit to 1.43.38 by @​thomhurst in
thomhurst/TUnit#5858


**Full Changelog**:
thomhurst/TUnit@v1.43.38...v1.43.41

## 1.43.38

<!-- Release notes generated using configuration in .github/release.yml
at v1.43.38 -->

## What's Changed
### Other Changes
* feat(playwright): add TUnitPlaywrightSettings defaults by @​thomhurst
in thomhurst/TUnit#5859


**Full Changelog**:
thomhurst/TUnit@v1.43.37...v1.43.38

## 1.43.37

<!-- Release notes generated using configuration in .github/release.yml
at v1.43.37 -->

## What's Changed
### Other Changes
* docs: clarify MethodDataSourceAttribute.Factory is
source-generator-managed by @​Copilot in
thomhurst/TUnit#5835
* fix(assertions): skip ref-struct members in IsEquivalentTo (#​5841) by
@​thomhurst in thomhurst/TUnit#5842
* feat(playwright): add composition-based fixtures by @​thomhurst in
thomhurst/TUnit#5840
### Dependencies
* chore(deps): update tunit to 1.43.11 by @​thomhurst in
thomhurst/TUnit#5821
* chore(deps): update dependency polyfill to 10.4.0 by @​thomhurst in
thomhurst/TUnit#5830
* chore(deps): update dependency polyfill to 10.4.0 by @​thomhurst in
thomhurst/TUnit#5829
* chore(deps): update react to ^19.2.6 by @​thomhurst in
thomhurst/TUnit#5839
* chore(deps): update dependency polyfill to 10.5.0 by @​thomhurst in
thomhurst/TUnit#5848
* chore(deps): update dependency polyfill to 10.5.0 by @​thomhurst in
thomhurst/TUnit#5849
* chore(deps): update aspire to 13.3.0 by @​thomhurst in
thomhurst/TUnit#5851
* chore(deps): update dependency brace-expansion to v5.0.6 by
@​thomhurst in thomhurst/TUnit#5853
* chore(deps): update dependency polyfill to 10.5.1 by @​thomhurst in
thomhurst/TUnit#5854
* chore(deps): update dependency polyfill to 10.5.1 by @​thomhurst in
thomhurst/TUnit#5855
* chore(deps): update verify to 31.16.3 by @​thomhurst in
thomhurst/TUnit#5856


**Full Changelog**:
thomhurst/TUnit@v1.43.11...v1.43.37

Commits viewable in [compare
view](thomhurst/TUnit@v1.43.11...v1.44.0).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit.Core&package-manager=nuget&previous-version=1.43.11&new-version=1.44.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This was referenced May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant